package com.cn.wanxi.service.impl;

import com.cn.wanxi.common.ParseTool;
import com.cn.wanxi.common.RedisNumTool;
import com.cn.wanxi.common.ThreadTool;
import com.cn.wanxi.entity.ProductEntity;
import com.cn.wanxi.entity.ResultEntity;
import com.cn.wanxi.mapper.ProductMapper;
import com.cn.wanxi.service.IProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;

import java.util.ArrayList;
import java.util.List;

@Service
public class ProductServiceImpl implements IProductService {
    @Autowired
    private ProductMapper productMapper;

    @Override
    public ResultEntity add(ProductEntity productEntity) {
        int result = productMapper.add(productEntity);
        resetCache(result, 0);
        return ResultEntity.success(result);
    }

    @Override
    public ResultEntity update(ProductEntity productEntity) {
        int result = productMapper.update(productEntity);
        resetCache(result, productEntity.getId());
        return ResultEntity.success(result);
    }

    @Override
    public ResultEntity delete(ProductEntity productEntity) {
        int result = productMapper.delete(productEntity);
        resetCache(result, productEntity.getId());
        return ResultEntity.success(result);
    }

    @Override
    public List<ProductEntity> findAll(ProductEntity productEntity) {
        final List<ProductEntity>[] list = new List[]{new ArrayList<>()};
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                list[0] = findAllCache(productEntity);
            }
        });
        thread.start();
        ThreadTool.ThreadSleep(thread);
        return list[0];
    }

    @Override
    public ResultEntity<ProductEntity> findById(ProductEntity productEntity) {
        final ProductEntity[] model = {new ProductEntity()};
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                model[0] = findByIdCache(productEntity);
            }
        });
        thread.start();
        ThreadTool.ThreadSleep(thread);
        return ResultEntity.success(model[0]);
    }

    @Override
    public Integer getCount(ProductEntity productEntity) {
        final int[] result = {-1};
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                result[0] = findCountCache(productEntity);
            }
        });
        thread.start();
        ThreadTool.ThreadSleep(thread);
        return result[0];
    }

    @Override
    public ResultEntity findPrevious(ProductEntity productEntity) {
        ProductEntity model = productMapper.findPrevious(productEntity);
        if (model == null) {
            return ResultEntity.failed();
        }
        return ResultEntity.success(model);
    }

    @Override
    public ResultEntity findNext(ProductEntity productEntity) {
        ProductEntity model = productMapper.findNext(productEntity);
        if (model == null) {
            return ResultEntity.failed();
        }
        return ResultEntity.success(model);
    }

    /**
     * 查找所有产品缓存
     *
     * @param productModel
     * @return
     */
    private synchronized List<ProductEntity> findAllCache(ProductEntity productModel) {
        List<ProductEntity> list = new ArrayList<>();
        Jedis jedis = new Jedis();
        jedis.select(RedisNumTool.REDIS_PRODUCT);
        boolean cache = jedis.exists("productModelId") && judgeModel(productModel);
        if (cache) {
            Long length = jedis.llen("productModelId");
            for (int i = 0; i < length; i++) {
                ProductEntity model = new ProductEntity();
                model.setId(ParseTool.StringToInt(jedis.lindex("productModelId", i)));
                model.setTypeId(ParseTool.StringToInt(jedis.lindex("productModelTypeId", i)));
                model.setName(jedis.lindex("productModelName", i));
                model.setImg(jedis.lindex("productModelImg", i));
                model.setTop(ParseTool.StringToInt(jedis.lindex("productModelTop", i)));
                model.setHot(ParseTool.StringToInt(jedis.lindex("productModelHot", i)));
                model.setOutline(jedis.lindex("productModelOutline", i));
                model.setDescribe(jedis.lindex("productModelDescribe", i));
                model.setMarketValue(ParseTool.StringToFloat(jedis.lindex("productModelMarketValue", i)));
                model.setPrice(ParseTool.StringToFloat(jedis.lindex("productModelPrice", i)));
                model.setEnable(ParseTool.StringToInt(jedis.lindex("productModelEnable", i)));
                model.setUpdateTime(jedis.lindex("productModelUpdateTime", i));
                list.add(model);
            }
        } else {
            list = productMapper.findAll(productModel);
            if (judgeModel(productModel)) {
                for (ProductEntity model :
                        list) {
                    jedis.rpush("productModelId", String.valueOf(model.getId()));
                    jedis.rpush("productModelTypeId", String.valueOf(model.getTypeId()));
                    jedis.rpush("productModelName", model.getName());
                    jedis.rpush("productModelImg", model.getImg());
                    jedis.rpush("productModelTop", String.valueOf(model.getTop()));
                    jedis.rpush("productModelHot", String.valueOf(model.getHot()));
                    jedis.rpush("productModelOutline", model.getOutline());
                    jedis.rpush("productModelDescribe", model.getDescribe());
                    jedis.rpush("productModelMarketValue", String.valueOf(model.getMarketValue()));
                    jedis.rpush("productModelPrice", String.valueOf(model.getPrice()));
                    jedis.rpush("productModelEnable", String.valueOf(model.getEnable()));
                    jedis.rpush("productModelUpdateTime", model.getUpdateTime());
                }
            }
        }
        return list;
    }

    /**
     * 根据产品id查找单个产品缓存
     *
     * @param productModel
     * @return
     */
    private synchronized ProductEntity findByIdCache(ProductEntity productModel) {
        ProductEntity model = new ProductEntity();
        Jedis jedis = new Jedis();
        jedis.select(RedisNumTool.REDIS_PRODUCT);
        String cacheName = "productModel_id_" + productModel.getId();
        boolean cache = jedis.exists(cacheName);
        if (cache) {
            model.setId(ParseTool.StringToInt(jedis.hget(cacheName, "id")));
            model.setTypeId(ParseTool.StringToInt(jedis.hget(cacheName, "typeId")));
            model.setName(jedis.hget(cacheName, "name"));
            model.setImg(jedis.hget(cacheName, "img"));
            model.setTop(ParseTool.StringToInt(jedis.hget(cacheName, "top")));
            model.setHot(ParseTool.StringToInt(jedis.hget(cacheName, "hot")));
            model.setOutline(jedis.hget(cacheName, "outline"));
            model.setDescribe(jedis.hget(cacheName, "describe"));
            model.setMarketValue(ParseTool.StringToFloat(jedis.hget(cacheName, "marketValue")));
            model.setPrice(ParseTool.StringToFloat(jedis.hget(cacheName, "price")));
            model.setEnable(ParseTool.StringToInt(jedis.hget(cacheName, "enable")));
            model.setUpdateTime(jedis.hget(cacheName, "updateTime"));
            model.setVisits(ParseTool.StringToInt(jedis.hget(cacheName, "visits")));
            jedis.hincrBy(cacheName, "visits", 1);
            /*设为热点*/
            if (Integer.parseInt(jedis.hget(cacheName, "visits")) == 100) {
                model.setHot(1);
                model.setStart("");
                model.setEnd("");
                productMapper.update(model);
            }
        } else {
            model = productMapper.findById(productModel);
            jedis.hset(cacheName, "id", String.valueOf(model.getId()));
            jedis.hset(cacheName, "typeId", String.valueOf(model.getTypeId()));
            jedis.hset(cacheName, "name", model.getName());
            jedis.hset(cacheName, "img", model.getImg());
            jedis.hset(cacheName, "top", String.valueOf(model.getTop()));
            jedis.hset(cacheName, "hot", String.valueOf(model.getHot()));
            jedis.hset(cacheName, "outline", model.getOutline());
            jedis.hset(cacheName, "describe", model.getDescribe());
            jedis.hset(cacheName, "marketValue", String.valueOf(model.getMarketValue()));
            jedis.hset(cacheName, "price", String.valueOf(model.getPrice()));
            jedis.hset(cacheName, "enable", String.valueOf(model.getEnable()));
            jedis.hset(cacheName, "updateTime", model.getUpdateTime());
            jedis.hset(cacheName, "visits", "1");
            /*取消热点*/
            if (Integer.parseInt(jedis.hget(cacheName, "visits")) == 1) {
                model.setHot(0);
                model.setStart("");
                model.setEnd("");
                productMapper.update(model);
            }
        }
        return model;
    }

    /**
     * 查找产品总数的缓存
     *
     * @param productModel
     * @return
     */
    private synchronized int findCountCache(ProductEntity productModel) {
        int result = -1;
        Jedis jedis = new Jedis();
        jedis.select(RedisNumTool.REDIS_PRODUCT);
        boolean cache = jedis.exists("productModelCount") && judgeModel(productModel);
        if (cache) {
            result = ParseTool.StringToInt(jedis.get("productModelCount"));
        } else {
            result = productMapper.getCount(productModel);
            if (judgeModel(productModel)) {
                jedis.set("productModelCount", String.valueOf(result));
            }
        }
        return result;
    }

    /**
     * 清除Redis内缓存
     *
     * @param result
     * @param id
     */
    private void resetCache(int result, int id) {
        if (result > 0) {
            Jedis jedis = new Jedis();
            jedis.select(RedisNumTool.REDIS_PRODUCT);
            jedis.del("productModelId", "productModelTypeId",
                    "productModelName", "productModelImg",
                    "productModelOutline", "productModelDescribe",
                    "productModelMarketValue", "productModelPrice",
                    "productModelTop", "productModelHot",
                    "productModelEnable", "productModelUpdateTime");
            jedis.del("productModelCount");
            jedis.del("productModel_id_" + id);
        }
    }

    /**
     * 判断model内是否有值
     * 没有值返回true
     *
     * @param model
     * @return
     */
    private boolean judgeModel(ProductEntity model) {
        return model.getId() == null &&
                model.getTypeId() == null &&
                model.getName() == null &&
                model.getImg() == null &&
                model.getOutline() == null &&
                model.getDescribe() == null &&
                model.getStart() == null &&
                model.getEnd() == null &&
                ParseTool.enableToInt(model.getEnable()) == 1 &&
                ParseTool.pageToInt(model.getPage()) == 1 &&
                ParseTool.productLimitToInt(model.getLimit()) == 12 &&
                model.getUpper() == null &&
                model.getLower() == null;
    }
}
